package ird.demo.service.impl;

import ird.demo.common.FormatUtil;
import ird.demo.domain.LdapUser;
import ird.demo.service.LdapService;

import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

import javax.naming.directory.DirContext;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.ldap.AuthenticationException;
import org.springframework.ldap.core.ContextMapper;
import org.springframework.ldap.core.DirContextAdapter;
import org.springframework.ldap.core.DirContextOperations;
import org.springframework.ldap.core.DistinguishedName;
import org.springframework.ldap.core.LdapTemplate;
import org.springframework.ldap.core.support.AbstractContextMapper;
import org.springframework.ldap.filter.EqualsFilter;
import org.springframework.ldap.filter.Filter;
import org.springframework.security.ldap.LdapUtils;
import org.springframework.stereotype.Service;

@Service
public class LdapServiceImpl implements LdapService {
	
	@Value("${ldap.baseDN}")
    private String baseDN;
	
	@Autowired
	private LdapTemplate ldapTemplate;

	
	
	// public void create(LdapUser ldapUser) {
	// DirContextAdapter context = new DirContextAdapter();
	// mapToContext(ldapUser, context);
	// ldapTemplate.bind(buildDn(ldapUser), context, null);
	// }
	//
	// public void update(LdapUser ldapUser) {
	// Name dn = buildDn(ldapUser);
	// DirContextAdapter context = (DirContextAdapter) ldapTemplate.lookup(dn);
	// mapToContext(ldapUser, context);
	// ldapTemplate.modifyAttributes(dn, context.getModificationItems());
	// }

	// public void delete(LdapUser ldapUser) {
	// ldapTemplate.unbind(buildDn(ldapUser));
	// }

	

	public LdapUser findByPrimaryKey(String userId) {
		// Name dn = buildDn(userId);
		DistinguishedName dn = new DistinguishedName();
		dn.add("cn", userId);
		return (LdapUser) ldapTemplate.lookup(dn, getLdapUsertMapper());
	}

	// public List findAll() {
	// EqualsFilter filter = new EqualsFilter("objectclass", "person");
	// return ldapTemplate.search(DistinguishedName.EMPTY_PATH,
	// filter.encode(), getContextMapper());
	// }

	protected ContextMapper getLdapUsertMapper() {
		return new LdapUserContextMapper();
	}

	// protected Name buildDn(LdapUser ldapUser) {
	// return buildDn(ldapUser.getUserId());
	// }

	// protected Name buildDn(String fullname, String company, String country) {
	// DistinguishedName dn = new DistinguishedName();
	// dn.add("c", country);
	// dn.add("ou", company);
	// dn.add("cn", fullname);
	// return dn;
	// }

	// protected Name buildDn(String usrId) {
	// DistinguishedName dn = new DistinguishedName();
	// dn.add("uid", usrId);
	// return dn;
	// }

	// protected void mapToContext(LdapUser ldapUser, DirContextAdapter context)
	// {
	// context.setAttributeValues("objectclass", new String[] { "top",
	// "person" });
	// context.setAttributeValue("cn", ldapUser.getUserId());
	// context.setAttributeValue("sn", ldapUser.getUserId());
	// context.setAttributeValue("description", ldapUser.getUserId());
	// }
	
//	public static Timestamp toTimestamp(String timestampStr, DateFormat df) throws Exception{
//		Date ts = df.parse(timestampStr);
//		return new Timestamp(ts.getTime());
//	}

	private static class LdapUserContextMapper implements ContextMapper {
		public LdapUser mapFromContext(Object ctx) {
			DirContextAdapter context = (DirContextAdapter) ctx;
			LdapUser ldapUser = new LdapUser();
			ldapUser.setUsrId(context.getStringAttribute("cn"));
			ldapUser.setAcctRevokedInd(context.getStringAttribute("acctrevoked"));
			ldapUser.setFailLoginNum(Integer.parseInt(context.getStringAttribute("faillogonnum")));
			ldapUser.setLoginAllowedInd(context.getStringAttribute("isloginallowed"));
			ldapUser.setPisUsrType(context.getStringAttribute("pisusertype"));
			ldapUser.setPwdChgReqInd(context.getStringAttribute("pwdchgreq"));
			ldapUser.setUpdateBy(context.getStringAttribute("updatedby"));
			ldapUser.setUsrLvl(context.getStringAttribute("userlevel"));
			ldapUser.setWebUsrDesc(context.getStringAttribute("webuserdesc"));
			
			try{
				ldapUser.setCrtTs(FormatUtil.toLdapTimestamp(context.getStringAttribute("createaccounttimestamp")));
				ldapUser.setLstLoginTs(FormatUtil.toLdapTimestamp(context.getStringAttribute("lastlogontimestamp")));
				ldapUser.setPwdLstUpdTs(FormatUtil.toLdapTimestamp(context.getStringAttribute("pwdlastupdtimestamp")));
				ldapUser.setUpdateTs(FormatUtil.toLdapTimestamp(context.getStringAttribute("updatets")));
			}
			catch(Exception e){
				e.printStackTrace();
			}
			System.out.println(ldapUser);

			return ldapUser;
		}
	}

//	public String getDnForUser(String uid) {
//		Filter f = new EqualsFilter("cn", uid);
//		List result = ldapTemplate.search(DistinguishedName.EMPTY_PATH,
//				f.toString(), new AbstractContextMapper() {
//					protected Object doMapFromContext(DirContextOperations ctx) {
//						return ctx.getNameInNamespace();
//					}
//				});
//
//		if (result.size() != 1) {
//			throw new RuntimeException("User not found or not unique");
//		}
//
//		return (String) result.get(0);
//	}
	
	public String getDnForUser(String uid){
		return "cn="+uid+","+baseDN;
	}

//	public boolean authenticate(String userId, String pwd) {
//		DirContext ctx = null;
//		try {
//			System.out.println("ldapTemplate=" + ldapTemplate);
//			String userDN = getDnForUser(userId);
//			System.out.println("===userDN="+userDN+",pwd="+pwd);
//			ctx = ldapTemplate.getContextSource().getContext(userDN,pwd);
//			System.out.println("ctx=" + ctx);
//			return true;
//		} 
//		catch (AuthenticationException e) {
//			// Context creation failed - authentication did not succeed
//			e.printStackTrace();
//			return false;
//		} 
//		catch (Exception e) {
//			// Context creation failed - authentication did not succeed
//			e.printStackTrace();
//			return false;
//		} finally {
//			// It is imperative that the created DirContext instance is always
//			// closed
//			LdapUtils.closeContext(ctx);
//		}
//	}
}
